package com.suray.system.run.util;

import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.core.utils.StringUtils;
import com.suray.wcs.service.core.path.api.impl.PortContainer;
import com.suray.wcs.service.enums.ConnectModel;
import com.suray.wcs.service.enums.PortModel;
import com.suray.wcs.service.system.entity.PortDB;
import com.suray.wcs.service.system.entity.PortTaskConfigDB;
import com.suray.wcs.service.system.entity.TaskDB;
import com.suray.wcs.service.system.service.impl.PortDBServiceImpl;
import com.suray.wcs.service.system.service.impl.TaskDBServiceImpl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class PortFuncUtil {
    private static final PortDBServiceImpl portDBService = SpringContextHolder.getBean(PortDBServiceImpl.class);
    private static final TaskDBServiceImpl taskDBService = SpringContextHolder.getBean(TaskDBServiceImpl.class);

    /**
     * 接驳的库口，任务数量 系数
     */
    private static final float CONNECT_PORT_TASK_NUM_FACT = 4;

    private static final int CONNECT_PORT_TASK_NUM_OFFSET = 4;

    /**
     * 库口集合转换成库口数据
     * @param ports
     * @return
     */
    public static String changeToPortsStr(List<PortDB> ports) {
        if (ports.size() == 0) {
            return "";
        }
        
        String str = "";
        str += ports.get(0).getPortId();
        for (int i = 1; i < ports.size(); i++) {
            str += "-" + ports.get(i).getPortId();
        }

        return str;
    }

    /**
     * 库口数据转换成库口集合
     * @param portsStr
     * @return
     */
    public static List<PortDB> changeToPortList(String portsStr) {
        if (StringUtils.isEmpty(portsStr)) {
            return new ArrayList<>();
        }

        List<PortDB> portDBS = new ArrayList<>();
        String[] portSs = portsStr.split("-");
        try {
            for (String ss : portSs) {
                portDBS.add(portDBService.getById(Integer.valueOf(ss)));
            }
        } catch (NumberFormatException e) {
            throw new RuntimeException("库口数据错误，无法转换");
        }

        return portDBS;
    }

    /**
     * 库口是否启用
     * @param portDB
     * @return
     */
    public static boolean isPortEnable(PortDB portDB) {
        return portDB.getStatus() == 0;
    }

    /**
     * 统计各库口当前的出库信息
     * @param taskDB
     * @param container
     * @return
     */
    public static List<PortContainer> analyzePortContainer(TaskDB taskDB, PortTaskContainer container,
                                                           boolean calcConnect) {
        List<PortContainer> portContainers = new ArrayList<>();
        List<PortDB> portDBS = PortFuncUtil.changeToPortList(taskDB.getOutPortsStr());
        int layer = taskDB.selectStartNode().getZ();
        for (PortDB portDB : portDBS) {
            if (!PortFuncUtil.isPortEnable(portDB)) {
                continue;
            }

            PortModel portModel = PortModel.parsePortType(portDB.getPortMode());
            if (portModel != PortModel.OUT_PORT && portModel != PortModel.IN_AND_OUT) {
                continue;
            }

            int taskNum = container.getTaskNum(portDB.getPortCode(), layer);
            if (calcConnect) {
                if (ConnectModel.NEED_CONNECT.getValue().equals(portDB.getConnectMode())) {
                    taskNum = (int) (0.99 + taskNum * CONNECT_PORT_TASK_NUM_FACT) + CONNECT_PORT_TASK_NUM_OFFSET;
                }
            }
            portContainers.add(new PortContainer(portDB, taskNum));
        }

        //连续出库时，路线只影响前几个任务，对后面的任务执行影响较小，且消耗太大，暂不考虑路径长短
        Collections.sort(portContainers, Comparator.comparingInt(o -> o.getTaskNum()));
        return portContainers;
    }

    /**
     * 解析各个库口的出库任务
     * @return
     * @param unFinishTask
     */
    public static PortTaskContainer analyzeOutPortTaskNum(List<TaskDB> unFinishTask) {
        PortTaskContainer container = new PortTaskContainer();
        for (TaskDB taskDB : unFinishTask) {
            if (taskDB.getTaskPortId() == null) {
                continue;
            }

            container.addTask(taskDB.getTaskPortId(), taskDB.selectStartNode().getZ());
        }

        return container;
    }

    /**
     * 校验库口是状态是否满足出库条件
     * @param portContainer
     * @param configDBS
     * @param layer
     * @return
     */
    public static boolean checkPortTaskConfig(PortContainer portContainer, List<PortTaskConfigDB> configDBS, int layer) {
        for (PortTaskConfigDB configDB : configDBS) {
            if (!configDB.getPortId().equals(portContainer.getPortDB().getPortId())) {
                continue;
            }

            if (!configDB.getLayer().equals(layer)) {
                continue;
            }

            if (configDB.getOutTaskNum() <= portContainer.getTaskNum()) {
                return false;
            }
        }

        return true;
    }
}
